
cmake_minimum_required(VERSION 3.30)

# CMake 脚本命令喵

message("\n======================================================================")
message("  --  脚本命令喵 CMake Script Command")
message("======================================================================\n")

message("    --  作用域喵 \n")

# =============================================================================
# 子项目、函数都会生成新的作用域喵，宏不会生成新的作用域喵

# 用 block 和 endblock 可用于创建作用域喵
#   block(PROPAGATE 外传的变量 ...) # 创建变量作用域喵， endblock 之后变量将置空，只会覆盖 PROPAGATE 指定的变量
#   block(SCOPE POLICIES) # 不创建变量作用域喵， endblock 之后变量保持原值

set(var1_for_block "OldVal1喵")
set(var2_for_block "OldVal2喵")
unset(var3_for_block)
message("block VARIABLES 测试喵： var1 = " ${var1_for_block} ", var2 = " ${var2_for_block} ", var3 = " ${var3_for_block})
block(PROPAGATE var1_for_block) # 创建新作用域喵，指定 var1 将回传至父作用域
  message("    in block VARIABLES var1 = " ${var1_for_block} ", var2 = " ${var2_for_block} ", var3 = " ${var3_for_block})
  set(var1_for_block "NewVal1喵") # 操作新作用域的变量， endblock 之后将置空喵，只会覆盖 PROPAGATE 指定的变量喵
  set(var2_for_block "NewVal2喵")
  set(var3_for_block "NewVal3喵")
  message("   out block VARIABLES var1 = " ${var1_for_block} ", var2 = " ${var2_for_block} ", var3 = " ${var3_for_block})
endblock()
message(" after block VARIABLES var1 = " ${var1_for_block} ", var2 = " ${var2_for_block} ", var3 = " ${var3_for_block} "\n")

set(var1_for_block "OldVal1喵")
set(var2_for_block "OldVal2喵")
unset(var3_for_block)
message("block POLICIES 测试喵： var1 = " ${var1_for_block} ", var2 = " ${var2_for_block} ", var3 = " ${var3_for_block})
block(SCOPE_FOR POLICIES) # 不创建作用域，仍然是原来作用域喵
  message("    in block POLICIES var1 = " ${var1_for_block} ", var2 = " ${var2_for_block} ", var3 = " ${var3_for_block})
  set(var1_for_block "NewVal1喵")
  set(var2_for_block "NewVal2喵")
  set(var3_for_block "NewVal3喵")
  message("   out block POLICIES var1 = " ${var1_for_block} ", var2 = " ${var2_for_block} ", var3 = " ${var3_for_block})
endblock()
message(" after block POLICIES var1 = " ${var1_for_block} ", var2 = " ${var2_for_block} ", var3 = " ${var3_for_block} "\n")

message("    --  变量喵 \n")

# =============================================================================
# 用 ${变量} 获取变量的值喵
# 用 set(变量 [值] [PARENT_SCOPE]) 设置变量的值喵，未指定值则设置为空喵，指定 PARENT_SCOPE 则操作父作用域的变量喵
# 用 unset(变量 [PARENT_SCOPE]) 置空变量喵，指定 PARENT_SCOPE 则操作父作用域的变量喵
set(var1_for_tsps "OldVal1喵")
set(var2_for_tsps "OldVal2喵")
message("变量作用域测试喵： var1 = " ${var1_for_tsps} ", var2 = " ${var2_for_tsps})
block() # 新作用域喵
  message("    in function var1 = " ${var1_for_tsps} ", var2 = " ${var2_for_tsps})
  set(var1_for_tsps "NewVal1喵") # 操作新作用域的变量， endblock 之后将置空喵
  set(var2_for_tsps "NewVal2喵" PARENT_SCOPE) # 操作父作用域的变量喵
  message("   out function var1 = " ${var1_for_tsps} ", var2 = " ${var2_for_tsps})
endblock()
message(" after function var1 = " ${var1_for_tsps} ", var2 = " ${var2_for_tsps} "\n")

# =============================================================================
# 其他变量喵

# 用 set(<variable> <value>... CACHE <type> <docstring> [FORCE]) # 设置缓存的值喵，type 可为 BOOL FILEPATH PATH STRING INTERNAL ，指定 FORCE 则覆盖现有值，默认不覆盖

# 用 set(ENV{<variable>} [<value>]) # 设置环境变量的值喵

# 用 option(变量 "帮助信息" 默认值) 指定一个开关喵，可以显示在 cmake GUI ，命名不可以冲突
option(SWITCH1_DEFAULT_ON "这是一个默认打开开关喵" ON)
option(SWITCH2_DEFAULT_OFF "这是一个默认不打开的开关喵") # 不指定默认值默认为关喵
message("开关演示喵： 开关1 = " ${SWITCH1_DEFAULT_ON} " 开关2 = " ${SWITCH2_DEFAULT_OFF} "\n")


# 用 mark_as_advanced([CLEAR|FORCE] <var1> ...) 将变量设置为高级喵。指定 FORCE 将变量设置为高级， CLEAR 将变量设置为普通
#   高级变量不会显示在任何 cmake GUI 中，除非 "显示高级" 选项打开喵

message("    --  函数和宏喵 \n")

# =============================================================================
# 用 function(函数名 形参 ...) 和 endfunction() 用声明一个函数喵
# 使用 return(PROPAGATE 变量 ...) 将变量传出为返回值喵
# 传入的参数数量为 ARGC ，参数分别被命名为 ARGV0, ARGV1, ARGV2 ... ，不匹配形参列表的参数的保存在 ARGN 中
function(f_test_fun val_a val_b)
  message("传参测试喵： 函数参数数量 argc = " ${ARGC})
  set(argv_index 0) # i = 0
  while(argv_index LESS ${ARGC}) # while(i < ARGC)
    set(argvi "ARGV${argv_index}") # 设置 argvi 为字符串 ARGV0, ARGV1, ARGV2 ...
    message(${argvi} " : " ${${argvi}})
    math(EXPR argv_index "${argv_index} + 1" OUTPUT_FORMAT DECIMAL) # i++
  endwhile()
  message("函数剩余参数 ARGN : " ${ARGN})
  set(f_test_fun_ret ${ARGV0} " - " ${ARGV1}) # 函数内部创建新作用域，操作新作用域变量喵
  message("函数 a_in = " ${val_a} " b_in = " ${val_b} " ret = " ${f_test_fun_ret})
  return(PROPAGATE f_test_fun_ret) # 使用 return(PROPAGATE 变量 ...) 将变量传出喵
endfunction()
f_test_fun("A_sub喵" "B_sub喵" "C_etc喵" "D_etc喵")
message("ret = " ${f_test_fun_ret} "\n")

# =============================================================================
# 宏的用法类似于函数喵，区别：
#   宏中 ARGN、ARGC、ARGV0、ARGV1 等在宏中为字符串替换而不是变量喵
#   宏不产生新的作用域喵
macro(f_test_macro val_a val_b ref_ret)
  message("宏测试喵： in macro A = " ${val_a} " B = " ${val_b} " ret = " ${ref_ret})
  set(${ref_ret} ${val_a} " - " ${val_b})
  message("in macro ref_ret.name = " ${ref_ret} " , ref_ret.value = " ${${ref_ret}}) # 变量的名称和值喵
endmacro()
f_test_macro("A_sub" "B_sub" ret_macro)
message("ret = " ${ret_macro} "\n")

message("    --  参数类型喵 \n")

# =============================================================================
# 参数有三种类型喵，分别是 开关、单值参数、多值参数

# 可用 cmake_parse_arguments 解析变量并自动生成名为 "prefix_变量名" 的变量，仅用于函数
# 形式 1 喵
# cmake_parse_arguments(<prefix> # 生成的变量的前缀
#   <options> <one_value_keywords> <multi_value_keywords> 
#   <args>...) # 要解析的变量列表喵
# 形式 2 喵
# cmake_parse_arguments(PARSE_ARGV <N> # 用于读取从第 N 个开始的参数喵
#   <prefix> # 生成的变量的前缀
#   <options> <one_value_keywords> <multi_value_keywords>) # 参数表喵
function(test_parse_args_parser)
    set(optionArgs OPTA) # 开关喵 值为 True 或 False，名称后不跟值，出现为 True 不出现为 False
    set(oneValArgs ONEA) # 单值变量喵 名称后跟一个值，其余值舍弃
    set(mulValArgs MULA) # 多值变量喵 名称后跟多个值
    cmake_parse_arguments(arg "${optionArgs}" "${oneValArgs}" "${mulValArgs}" ${ARGN})
    message("参数解析测试喵： ARGN " ${ARGN})
    message("开关喵 arg_OPTA : " ${arg_OPTA})
    message("单值变量喵 arg_ONEA : " ${arg_ONEA})
    message("多值变量喵 arg_MULA : " ${arg_MULA})
    message("其他参数喵 arg_UNPARSED_ARGUMENTS " ${arg_UNPARSED_ARGUMENTS}) # 不匹配形参的参数喵
    message("缺省参数喵 arg_KEYWORDS_MISSING_VALUES " ${arg_KEYWORDS_MISSING_VALUES} "\n") # 未传入值的形数喵
endfunction()
test_parse_args_parser(MULA mul_1 mul_2 ONEA one_a OPTA)

message("    --  流程控制喵 \n")

# =============================================================================
# 条件语法喵

# 基本条件语法喵
#   真值： 1、ON、YES、TRUE、Y、非零数(包括浮点数)
#   假值： 0、OFF、NO、FALSE、N、IGNORE、NOTFOUND、空字符串、"-NOTFOUND"结尾
#   布尔运算： AND、OR、NOT
#   数学运算： LESS、LESS_EQUAL、GREATER、GREATER_EQUAL、EQUAL
#   字符串运算： STRLESS、STRLESS_EQUAL、STRGREATER、STRGREATER_EQUAL、STREQUAL
#   版本运算： VERSION_LESS、VERSION_LESS_EQUAL、VERSION_GREATER、VERSION_GREATER_EQUAL、VERSION_EQUAL
#   路径运算： PATH_EQUAL
# 其他条件语法喵
#   if(COMMAND <command-name>) # 给定名称是可以调用的命令、宏或函数为真
#   if(POLICY <policy-id>) # 是现有策略为真
#   if(TARGET <target-name>) # 给定目标通过 add_executable add_library 或 add_custom_target 等正确创建为真
#   if(TEST <test-name>) # 给定测试由 add_test 等命令正确创建为真
#   if(DEFINED <name>|CACHE{<name>}|ENV{<name>}) # 定义了名为 <name> 的变量、缓存变量或环境变量为真
#   if(<variable|string> IN_LIST <variable>) # 在列表中为真
#   if(EXISTS <path-to-file-or-directory>) # 存在该文件或目录为真
#   if(IS_READABLE <path-to-file-or-directory>) # 文件或目录可读为真
#   if(IS_WRITABLE <path-to-file-or-directory>) # 文件或目录可写为真
#   if(IS_EXECUTABLE <path-to-file-or-directory>) # 文件或目录可执行为真
#   if(<file1> IS_NEWER_THAN <file2>) # file1 新或一个文件不存在为真，一样新也为真
#   if(IS_DIRECTORY <path>) # 是目录为真
#   if(IS_SYMLINK <path>) # 是符号链接为真
#   if(IS_ABSOLUTE <path>) # 是绝对路径为真，空路径为假
#   if(<variable|string> MATCHES <regex>) # 满足正则表达式为真

# =============================================================================
# if 分支喵
# if(<condition>)
#   <commands>
# elseif(<condition>)
#   <commands>
# else()
#   <commands>
# endif()

# =============================================================================
# 循环喵，循环中可使用 break() 和 continue() 控制流程

# while 循环喵
# while(<condition>)
#   <commands>
# endwhile()

# for "初值、末值、步长" 型循环喵
# foreach(<loop_var> <items>)
#   items 可为：
#     RANGE <stop> # 从 0 <= loop_var <= stop
#     RANGE <start> <stop> [<step>] # 初值 末值 步长
foreach(X RANGE 3)
  message(" RANGE 循环测试喵： X = " ${X})
endforeach()
message("\n")

# foreach 遍历列表循环喵
# foreach(<loop_var> IN [LISTS [<lists>]] [ITEMS [<items>]])
#   foreach(<loop_var> IN LISTS <lists>...) 与 foreach(<loop_var> IN ITEMS <item>...) 等价
set(A_list_test_for_each "Hello" "World")
set(B_list_test_for_each "Head" "Enlarger")
foreach(X IN LISTS A_list_test_for_each B_list_test_for_each)
  message("遍历循环测试喵： X = " ${X})
endforeach()
message("\n")

# =============================================================================
# 事件喵

# 可使用 variable_watch(<variable> [<command>]) 监视变量喵，当变量变化时触发事件
#   事件 command 的格式为 COMMAND(<variable> <access> <value> <current_list_file> <stack>)
function(test_watcher variable access value current_list_file stack)
  message("变量监视测试喵： variable: " ${variable}) # 变量名喵
  message("access: " ${access}) # READ_ACCESS、UNKNOWN_READ_ACCESS、MODIFIED_ACCESS、UNKNOWN_MODIFIED_ACCESS、REMOVED_ACCESS
  message("value: " ${value}) # 值喵
  message("current_list_file: " ${current_list_file}) # 进行访问的文件的完整路径喵
  message("stack: " ${stack} "\n") # 调用栈喵
endfunction()
variable_watch(test_wathcer_var test_watcher)
set(test_wathcer_var 0)

message("    --  Config File 配置文件喵 \n")

# =============================================================================
# 配置文件喵，使用输入文件为模版生成文件
#   输入文件中 "@变量@" "${变量}" "$CACHE{变量}" 的变量以及被引用为 "$ENV{变量}" 的环境变量会被替换为对应变量值
#   输入文件中 "#cmakedefine 变量 ..." 会根据开关  "变量_ENABLE" 的值被替换为 "#define 变量 ..." 或 "/* #undef 变量 */"
# configure_file(<input> # 输入文件，默认目录为 CMAKE_CURRENT_SOURCE_DIR
#   <output> # 输出文件，默认目录为 CMAKE_CURRENT_BINARY_DIR
#   [permissions] # 输出文件的权限设置，默认为 USE_SOURCE_PERMISSIONS ，可为 NO_SOURCE_PERMISSIONS USE_SOURCE_PERMISSIONS FILE_PERMISSIONS
#   [COPYONLY] # 指定该值则原样复制不替换变量，与 NEWLINE_STYLE 设置冲突
#   [ESCAPE_QUOTES] # 用反斜杠转义任何替换的引号
#   [@ONLY] # 将变量替换限制为 "@变量@" 形式的引用
#   [NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF]) # 换行样式

message("    --  Package 管理喵 \n")

# =============================================================================
# 用 cmake_pkg_config 加载一个 Package 文件并生成相关变量和目标喵
# cmake_pkg_config(EXTRACT <package> [<version>] # 库名称和版本喵
#   [REQUIRED] # 如果未找到则报错喵
#   [EXACT] # 要求版本完全匹配喵
#   [QUIET] # 不显示消息喵
#   [STRICTNESS <mode>] # 指定验证包文件的严格程度喵，可为 STRICT PERMISSIVE BEST_EFFORT 
#   [ENV_MODE <mode>] # 指定查询的环境变量喵，可为 FDO PKGCONF IGNORE 
#   [DISABLE_UNINSTALLED <bool>] # 禁用搜索已卸载的软件包喵
#   [PC_LIBDIR <path>...] # pkg-config 环境变量 PKG_CONFIG_LIBDIR
#   [PC_PATH <path>...] # pkg-config 环境变量 PKG_CONFIG_PATH
#   [PC_SYSROOT_DIR <path>] # pkg-config 环境变量 PKG_CONFIG_SYSROOT_DIR
#   [TOP_BUILD_DIR <path>] #  pkg-config 环境变量 PKG_CONFIG_TOP_BUILD_DIR
#   [SYSTEM_INCLUDE_DIRS <path>...] # 系统包含目录
#   [SYSTEM_LIBRARY_DIRS <path>...] # 系统库目录
#   [ALLOW_SYSTEM_INCLUDES <bool>] # 保留系统包含目录
#   [ALLOW_SYSTEM_LIBS <bool>]) # 保留系统库目录

cmake_path(SET sample_package_path "Resources/sample_package.pc")
cmake_path(ABSOLUTE_PATH sample_package_path)
message("加载包测试喵，加载： " ${sample_package_path})
cmake_pkg_config(EXTRACT ${sample_package_path})
message("CMAKE_PKG_CONFIG_NAME = " ${CMAKE_PKG_CONFIG_NAME})
message("CMAKE_PKG_CONFIG_DESCRIPTION = " ${CMAKE_PKG_CONFIG_DESCRIPTION})
message("CMAKE_PKG_CONFIG_VERSION = " ${CMAKE_PKG_CONFIG_VERSION})
message("CMAKE_PKG_CONFIG_PROVIDES = " ${CMAKE_PKG_CONFIG_PROVIDES})
message("CMAKE_PKG_CONFIG_REQUIRES = " ${CMAKE_PKG_CONFIG_REQUIRES})
message("CMAKE_PKG_CONFIG_CONFLICTS = " ${CMAKE_PKG_CONFIG_CONFLICTS})
message("CMAKE_PKG_CONFIG_CFLAGS = " ${CMAKE_PKG_CONFIG_CFLAGS})
message("CMAKE_PKG_CONFIG_INCLUDES = " ${CMAKE_PKG_CONFIG_INCLUDES})
message("CMAKE_PKG_CONFIG_COMPILE_OPTIONS = " ${CMAKE_PKG_CONFIG_COMPILE_OPTIONS})
message("CMAKE_PKG_CONFIG_LIBS = " ${CMAKE_PKG_CONFIG_LIBS})
message("CMAKE_PKG_CONFIG_LIBDIRS = " ${CMAKE_PKG_CONFIG_LIBDIRS})
message("CMAKE_PKG_CONFIG_LIBNAMES = " ${CMAKE_PKG_CONFIG_LIBNAMES})
message("CMAKE_PKG_CONFIG_LINK_OPTIONS = " ${CMAKE_PKG_CONFIG_LINK_OPTIONS})
# message("CMAKE_PKG_CONFIG_*_PRIVATE = " ${CMAKE_PKG_CONFIG_*_PRIVATE}) # 从 CFLAGS LIBS REQUIRES 派生的变量内容
message("CMAKE_PKG_CONFIG_LIBS_PRIVATE = " ${CMAKE_PKG_CONFIG_LIBS_PRIVATE} "\n")

# =============================================================================
# find_package 重载喵

# 依赖提供将重定向 find_package() 或 FetchContent_MakeAvailable() 等到自定义实现喵
# 如无满足要求的自定义实现，将使用默认实现喵

# 使用 cmake_language(SET_DEPENDENCY_PROVIDER) 重定义 find_package 或 FetchContent_MakeAvailable
# cmake_language(SET_DEPENDENCY_PROVIDER <command> # 自定义的支持方法，应该是一个宏喵
#   SUPPORTED_METHODS <methods>...) # 替换的支持方法喵， method 可为 FIND_PACKAGE 或 FETCHCONTENT_MAKEAVAILABLE_SERIAL

# 使用时，需在顶级项目中，将重定义提供依赖的 cmake 文件添加到 CMAKE_PROJECT_TOP_LEVEL_INCLUDES 中
# 然后在第一次创建项目时将加载并执行喵，如：
#   set(CMAKE_PROJECT_TOP_LEVEL_INCLUDES Resources/my_provide.cmake) # 将在第一次运行 project 命令时被包含喵
#   project(HelloTest_ForMyProvide) # 创建项目并包含 my_provide.cmake ，重定向 find_package
#   find_package(Test) # 将使用重载的方法喵
# 本文件为子项目，该测试不可用喵

# =============================================================================
# 查找包， find_package 和其他查找命令实现通用的选项喵
# find_package(<PackageName> [version] # 包名和版本喵
#   [EXACT] [QUIET] [MODULE] # 使用哪种模式查找喵， MODULE 则不能使用 Config 模式， EXACT 要求严格匹配， QUIET 表示查找失败不输出提示
#   [[COMPONENTS] [components...]] # 查找包的特定组件
#   [OPTIONAL_COMPONENTS components...] # 可选的组件
#   [CONFIG|NO_MODULE] # 采用 Config 模式
#   [GLOBAL] # 全局
#   [NO_POLICY_SCOPE] # 不创建新的策略
#   [BYPASS_PROVIDER] # 重定义 find_package 时使用该选项调用系统的 find_package
#   [CONFIGS config1 [config2 ...]] # 可能的配置文件的名字
#   [NO_CMAKE_PACKAGE_REGISTRY] # 排除目录 CMAKE_PACKAGE_REGISTRY
#   [NO_CMAKE_SYSTEM_PACKAGE_REGISTRY] # 不使用系统软件包注册表
#   [NO_CMAKE_BUILDS_PATH] # Deprecated; does nothing 弃用项喵没有用喵
#   [NAMES name1 [name2 ...]]
#   [REQUIRED]
#   [HINTS path1 [path2 ... ]] [PATHS path1 [path2 ... ]]
#   [REGISTRY_VIEW  (64|32|64_32|32_64|HOST|TARGET|BOTH)]
#   [PATH_SUFFIXES suffix1 [suffix2 ...]]
#   [NO_DEFAULT_PATH]
#   [NO_PACKAGE_ROOT_PATH]
#   [NO_CMAKE_PATH]
#   [NO_CMAKE_ENVIRONMENT_PATH]
#   [NO_SYSTEM_ENVIRONMENT_PATH]
#   [NO_CMAKE_SYSTEM_PATH]
#   [NO_CMAKE_INSTALL_PREFIX]
#   [CMAKE_FIND_ROOT_PATH_BOTH |
#     ONLY_CMAKE_FIND_ROOT_PATH |
#     NO_CMAKE_FIND_ROOT_PATH])

# =============================================================================
# 查找成功后，将从包中获取包名开头（有时候是大写）的一系列变量喵，变量后缀为约定俗成，如：
#   Xxx_INCLUDE_DIRS Xxx_LIBRARIES Xxx_DEFINITIONS Xxx_EXECUTABLE
#   Xxx_YYY_EXECUTABLE Xxx_LIBRARY_DIRS Xxx_ROOT_DIR Xxx_VERSION_VV
#   Xxx_WRAP_YY Xxx_Yy_FOUND Xxx_FOUND Xxx_NOT_FOUND_MESSAGE
#   Xxx_RUNTIME_LIBRARY_DIRS Xxx_VERSION Xxx_VERSION_MAJOR Xxx_VERSION_MINOR
#   Xxx_VERSION_PATCH Xxx_LIBRARY Xxx_Yy_LIBRARY Xxx_INCLUDE_DIR Xxx_Yy_INCLUDE_DIR

cmake_path(SET sh_getline_path "Resources/GetLine.sh")
cmake_path(ABSOLUTE_PATH sh_getline_path)
message("Shell 脚本的路径： " ${sh_getline_path})
message("即将加载 Shell 脚本 GetLine 通过黑魔法获取实时输入喵，请输入要查找的包！") # 黑魔法的解析在 execute_process 章节
execute_process(COMMAND bash ${sh_getline_path} OUTPUT_VARIABLE sh_getline_str COMMAND_ECHO STDOUT) # 执行 shell 命令 echo
message("你要查找的包： " ${sh_getline_str} " 马上开始查询！")
find_package(${sh_getline_str})
set(pkg_suffix "_FOUND" "_VERSION" "_ROOT_DIR" "_DIR" "_DEFINITIONS" 
  "_INCLUDES" "_INCLUDE_DIR" "_INCLUDE_DIRS" 
  "_LIBS" "_LIBRARY" "_LIBRARIES" "_LIBRARY_DIRS" "_EXECUTABLE" "_RUNTIME_LIBRARY_DIRS")
foreach (suffix_item IN LISTS pkg_suffix)
  set(item_fullname ${sh_getline_str})
  string(TOUPPER ${sh_getline_str} item_fullname_upper)
  string(APPEND item_fullname ${suffix_item})
  message("${item_fullname} = " ${${item_fullname}})
  string(APPEND item_fullname_upper ${suffix_item})
  message("${item_fullname_upper} = " ${${item_fullname_upper}})
endforeach()

# =============================================================================
# 生成包配置文件，生成 <PackageName>Config.cmake 文件，需先包含 CMakePackageConfigHelpers
# configure_package_config_file(<input> <output> # 输入和输出文件，与 configure_file 类似
#   INSTALL_DESTINATION <path> # 安装位置
#   [PATH_VARS <var1> <var2> ... <varN>] # 安装位置的变量，由 input 使用
#   [NO_SET_AND_CHECK_MACRO] # 不检查引用的文件或目录是否实际存在
#   [NO_CHECK_REQUIRED_COMPONENTS_MACRO] # 不检查是否找到所需的组件
#   [INSTALL_PREFIX <path>]) # 安装路径前缀

# =============================================================================
# 生成包版本文件，生成 <PackageName>ConfigVersion.cmake 文件，需先包含 CMakePackageConfigHelpers
# write_basic_package_version_file(<filename> # 文件名
#   [VERSION <major.minor.patch>] # 版本
#   COMPATIBILITY <AnyNewerVersion|SameMajorVersion|SameMinorVersion|ExactVersion> # 兼容模式
#   [ARCH_INDEPENDENT]) # 安装的包版本是兼容的，适用于只有头文件的库或没有二进制文件的类似包

message("    --  查找喵 find \n")

# =============================================================================
# 通用基本选项喵
#   [HINTS [path | ENV var]... ] [PATHS [path | ENV var]... ] # 除默认位置外，指定要搜索的目录
#   [REGISTRY_VIEW (64|32|64_32|32_64|HOST|TARGET|BOTH)] # 查找注册表
#   [PATH_SUFFIXES suffix1 [suffix2 ...]] # 在每个目录位置下面指定要检查的其他子目录
#   [VALIDATOR function] # 过滤器
#   [DOC "cache documentation string"] # 指定 <VAR> 缓存项的文档字符串
#   [NO_CACHE] # 搜索结果将存储在一个普通变量中，不保存在缓存中
#   [REQUIRED] # 如果没有找到任何东西，则停止处理并给出错误消息
#   [NO_DEFAULT_PATH] # 排除目录 DEFAULT_PATH
#   [NO_PACKAGE_ROOT_PATH] # 排除目录 PACKAGE_ROOT_PATH
#   [NO_CMAKE_PATH] # 排除目录 CMAKE_PATH
#   [NO_CMAKE_ENVIRONMENT_PATH] # 排除目录 CMAKE_ENVIRONMENT_PATH
#   [NO_SYSTEM_ENVIRONMENT_PATH] # 排除目录 SYSTEM_ENVIRONMENT_PATH
#   [NO_CMAKE_SYSTEM_PATH] # 排除目录 CMAKE_SYSTEM_PATH
#   [NO_CMAKE_INSTALL_PREFIX] # 排除目录 CMAKE_INSTALL_PREFIX
#   [CMAKE_FIND_ROOT_PATH_BOTH | # 按默认的顺序搜索
#     ONLY_CMAKE_FIND_ROOT_PATH | # 仅搜索重根目录和 CMAKE_STAGING_PREFIX 以下目录
#     NO_CMAKE_FIND_ROOT_PATH]) # 不使用 CMAKE_FIND_ROOT_PATH

# =============================================================================
# 其他查找喵， find_file 查找文件的完整路径， find_library 查找库， find_program 查找程序
# find_file find_library 或 find_program
#   (<VAR> # 保存结果的变量
#   name | NAMES name1 [name2 ...] # 在 find_library 和 find_program 中 name 为文件夹喵
#   [HINTS [path | ENV var]... ] [PATHS [path | ENV var]... ]
#   [REGISTRY_VIEW (64|32|64_32|32_64|HOST|TARGET|BOTH)] 
#   [PATH_SUFFIXES suffix1 [suffix2 ...]]
#   [VALIDATOR function]
#   [DOC "cache documentation string"]
#   [NO_CACHE]
#   [REQUIRED]
#   [NO_DEFAULT_PATH]
#   [NO_PACKAGE_ROOT_PATH]
#   [NO_CMAKE_PATH]
#   [NO_CMAKE_ENVIRONMENT_PATH]
#   [NO_SYSTEM_ENVIRONMENT_PATH]
#   [NO_CMAKE_SYSTEM_PATH]
#   [NO_CMAKE_INSTALL_PREFIX]
#   [CMAKE_FIND_ROOT_PATH_BOTH |
#     ONLY_CMAKE_FIND_ROOT_PATH |
#     NO_CMAKE_FIND_ROOT_PATH])

message("    --  数学表达式喵 \n")

# 用 math(EXPR <variable> "<expression>" [OUTPUT_FORMAT <format>]) 执行一个数学表达式
#   format 可为 HEXADECIMAL(十六进制) 或 DECIMAL(十进制)
math(EXPR value_math "100 * 0xFF + 66" OUTPUT_FORMAT DECIMAL)
message("数学表达式测试喵： 100 * 0xFF + 66 = " ${value_math} "\n")

message("    --  执行 CMake 喵\n")

# =============================================================================
# 使用 add_subdirectory 添加一个子目录并运行其中的 CMakeLists.txt ，子目录必须是一个 CMake 项目喵

# =============================================================================
# 使用 include 加载并运行 CMake 文件喵
# include(<file|module> # 要加载的 CMake 文件喵
#   [OPTIONAL] # 如指定，则找不到文件时不报错喵
#   [RESULT_VARIABLE <var>] # 保存完整的文件名，找不到文件为 NOTFOUND
#   [NO_POLICY_SCOPE]) # 不创建新的策略喵喵
include(Resources/test_for_inc.cmake)
message("\n")

# 可使用 include_guard([DIRECTORY|GLOBAL]) 防止重复包含文件喵
#   
# 在子文件使用下面的结构也可以防止重复包含喵：
#   if(__CURRENT_FILE_VAR__)
#     return() # 因重复包含退出了喵
#   endif()
#   set(__CURRENT_FILE_VAR__ TRUE)
include(Resources/test_for_inc.cmake)
message("\n")

# =============================================================================
# 使用 cmake_language 可执行 CMake 指令或代码喵

# 执行一条 CMake 命令喵
# cmake_language(CALL <command> [<arg>...]) # 约等于 command([args...])
cmake_language(CALL "message" "执行一条 CMake 命令测试喵： Hello World! \n")

# 执行多条 CMake 命令喵
# cmake_language(EVAL CODE <code>...) # 实际上是调用 CODE 后的内容喵
cmake_language(EVAL CODE 
  "message(执行多条 CMake 命令测试喵： 第一条 Hello World CmdA)
  message(执行多条 CMake 命令测试喵： 第二条 Hello World CmdB \n)")

# 在文件处理最后调用 CMake 命令喵
# cmake_language(DEFER <options>... CALL <command> [<arg>...])
#   options 可包含以下内容
#     DIRECTORY <dir> # 指定该级文件夹处理结束后调用本命令喵，默认为本级，只可指定为祖先级，如 ".."
#     ID id # 设置 ID ，需以下划线开头
#     ID_VAR id # 设置保存 ID 的变量喵
cmake_language(DEFER DIRECTORY ".." CALL message "延后命令调用测试喵： 本条消息将在父级文件处理最后显示喵 \n") # 会在最后调用喵
cmake_language(DEFER ID "_DeferedMessage" ID_VAR cm_lg_id CALL message "本条消息稍后会被取消喵") # 会在最后调用，并获取 ID
message("延后命令调用的 ID 测试喵： 某一条消息的 Id : " ${cm_lg_id} "\n")
cmake_language(DEFER CANCEL_CALL ${cm_lg_id}) # 取消一个回调喵

message("    --  执行外部指令喵 \n")

# =============================================================================
# 使用 execute_process 执行外部程序或脚本，每个命令的输出将通过管道传输到下一个命令
# execute_process(COMMAND <cmd1> [<arguments>] # 指令和参数
#   [COMMAND <cmd2> [<arguments>]]...  # 指令和参数
#   [WORKING_DIRECTORY <directory>] # 执行命令的目录
#   [TIMEOUT <seconds>] # 超时，单位为秒
#   [RESULT_VARIABLE <variable>] # 运行的最终结果。成功时为整数，失败时为错误信息
#   [RESULTS_VARIABLE <variable>] # 保存每条命令的结果。成功时为整数，失败时为错误信息
#   [OUTPUT_VARIABLE <variable>] [ERROR_VARIABLE <variable>] # 保存 stdout 或 stderr 到变量
#   [INPUT_FILE <file>] # 重定向 标准输入
#   [OUTPUT_FILE <file>] [ERROR_FILE <file>] # 重定向 stdout 或 stderr
#   [OUTPUT_QUIET] [ERROR_QUIET] # 忽略 stdout 或 stderr
#   [COMMAND_ECHO <where>] # 正在运行的命令将被回送到 <where> ，<where> 可为 STDERR STDOUT NONE
#   [OUTPUT_STRIP_TRAILING_WHITESPACE] [ERROR_STRIP_TRAILING_WHITESPACE] # 删除 stdout 或 stderr 的尾部空格
#   [ENCODING <name>] # 编码
#   [ECHO_OUTPUT_VARIABLE] [ECHO_ERROR_VARIABLE] # 标准输出或标准错误不会专门重定向到指定的变量
#   [COMMAND_ERROR_IS_FATAL <ANY|LAST>]) # ANY 则任何命令错误都会停止， LAST 则只有最后一条命令错误时停止
execute_process(COMMAND echo "执行外部指令测试喵： 准备执行 shell 指令 echo ！" COMMAND echo "执行外部指令测试喵： Hello World!" OUTPUT_VARIABLE exe_pro_output COMMAND_ECHO STDOUT) # 执行 shell 命令 echo
message("执行外部指令测试喵： 最终结果： " ${exe_pro_output} "\n")

# =============================================================================
# 使用 separate_arguments 将命令行参数解析为以分号分隔的列表
# separate_arguments(<variable> <mode> [PROGRAM [SEPARATE_ARGS]] <args>)
#   mode 可为： UNIX_COMMAND WINDOWS_COMMAND NATIVE_COMMAND
#   指定 PROGRAM 时， arg[0] 将被认为是可执行文件，后续为参数
#     指定 SEPARATE_ARGS 时，参数被拆分在结果中，否则参数为一个字符串整体
separate_arguments(out_test_cmd_args UNIX_COMMAND PROGRAM SEPARATE_ARGS "cc -c tst.c")
foreach(X IN LISTS out_test_cmd_args)
    message("解析命令行参数测试喵： the arg is : " ${X})
endforeach()
message("\n")

message("    --  文件和路径喵 \n")

# =============================================================================
# 路径喵

# 简要的说明喵：
# <path-var> 一个路径变量喵
# <input> 一个字符串文字表示一个或多个路径喵
# <input>... 零个或多个字符串文字参数喵
# <out-var> 保存结果的变量喵

# Decomposition 检索
#  cmake_path(GET <path-var> type <out-var>)
#    type ROOT_NAME ROOT_DIRECTORY ROOT_PATH FILENAME RELATIVE_PART PARENT_PATH
#  cmake_path(GET <path-var> EXTENSION|STEM [LAST_ONLY] <out-var>)

# Query 查询路径是否存在
#  cmake_path(HAS_type <path-var> <out-var>)
#    type 可为 ROOT_NAME ROOT_DIRECTORY ROOT_PATH FILENAME EXTENSION STEM RELATIVE_PART PARENT_PATH

#  cmake_path(IS_ABSOLUTE <path-var> <out-var>) # 是否是绝对路径
#  cmake_path(IS_RELATIVE <path-var> <out-var>) # 是否是相对路径
#  cmake_path(IS_PREFIX <path-var> <input> [NORMALIZE] <out-var>)
#  cmake_path(COMPARE <input1> <OP> <input2> <out-var>) # 比较路径

# Modification 修改
#  cmake_path(SET <path-var> [NORMALIZE] <input>) # 创建一个路径变量，令 path-var = input ，会按需自动转换形式
#  cmake_path(APPEND <path-var> [<input>...] [OUTPUT_VARIABLE <out-var>]) # 连接路径，令 path-var += input ，会按需自动转换形式
#  cmake_path(APPEND_STRING <path-var> [<input>...] [OUTPUT_VARIABLE <out-var>]) # 连接路径，令 path-var += input ，会按需自动转换形式
#  cmake_path(REMOVE_FILENAME <path-var> [OUTPUT_VARIABLE <out-var>]) # 删除文件名，文件变为目录
#  cmake_path(REPLACE_FILENAME <path-var> <input> [OUTPUT_VARIABLE <out-var>]) # 替换文件名
#  cmake_path(REMOVE_EXTENSION <path-var> [LAST_ONLY] [OUTPUT_VARIABLE <out-var>]) # 略
#  cmake_path(REPLACE_EXTENSION <path-var> [LAST_ONLY] <input> [OUTPUT_VARIABLE <out-var>]) # 略

# Generation 生成
#  cmake_path(NORMAL_PATH <path-var> [OUTPUT_VARIABLE <out-var>]) # 规范化路径
#  cmake_path(RELATIVE_PATH <path-var> [BASE_DIRECTORY <input>] [OUTPUT_VARIABLE <out-var>]) # 将 path-var 修改为相对目录
#  cmake_path(ABSOLUTE_PATH <path-var> [BASE_DIRECTORY <input>] [NORMALIZE] [OUTPUT_VARIABLE <out-var>])  # 将 path-var 修改为绝对目录

# Native Conversion 本地转换， CMake 路径和特定操作系统的路径转换
#  cmake_path(NATIVE_PATH <path-var> [NORMALIZE] <out-var>) # CMake -> 系统
#  cmake_path(CONVERT <input> TO_CMAKE_PATH_LIST <out-var> [NORMALIZE]) # 系统 -> CMake
#  cmake_path(CONVERT <input> TO_NATIVE_PATH_LIST <out-var> [NORMALIZE]) # CMake -> 系统

# Hashing 哈希
#  cmake_path(HASH <path-var> <out-var>) # 计算路径的哈希值

# =============================================================================
# 文件喵

# Reading 读
#   file(READ <filename> <out-var> [...]) # 从文件读取内容
#   file(STRINGS <filename> <out-var> [...]) # 从文件读取 ANSCII 字符串
#   file(<HASH> <filename> <out-var>)  # 计算文件的哈希值
#   file(TIMESTAMP <filename> <out-var> [...]) # 计算文件的修改时间
#   file(GET_RUNTIME_DEPENDENCIES [...]) # 递归获取给定文件所依赖的库列表，不适用于项目模式

# Writing 写
#   file({WRITE | APPEND} <filename> <content>...) # 写入文件
#   file({TOUCH | TOUCH_NOCREATE} [<file>...]) # 创建文件
#   file(GENERATE OUTPUT <output-file> [...])  # 为当前 CMake Generator 支持的每个 build configuration 生成一个输出文件
#   file(CONFIGURE OUTPUT <output-file> CONTENT <content> [...]) # 类似于 configure_file 命令

# Filesystem 文件系统
#   file({GLOB | GLOB_RECURSE} <out-var> [...] [<globbing-expr>...]) # 遍历子目录，使用类似 "*.txt" 的 globbing expressions 搜索文件
#   file(MAKE_DIRECTORY [<dir>...]) # 创建一个目录
#   file({REMOVE | REMOVE_RECURSE } [<files>...]) # 删除
#   file(RENAME <oldname> <newname> [...]) # 重命名
#   file(COPY_FILE <oldname> <newname> [...]) # 复制文件
#   file({COPY | INSTALL} <file>... DESTINATION <dir> [...]) # COPY 进阶的文件复制； INSTALL 类似于 install 命令
#   file(SIZE <filename> <out-var>) # 获取文件大小
#   file(READ_SYMLINK <linkname> <out-var>) # 查询符号链接并获取指向的路径
#   file(CREATE_LINK <original> <linkname> [...]) # 创建一个符号链接
#   file(CHMOD <files>... <directories>... PERMISSIONS <permissions>... [...]) # 更改文件权限
#   file(CHMOD_RECURSE <files>... <directories>... PERMISSIONS <permissions>... [...]) # 更改文件夹权限

# Path Conversion 路径转换
#   file(REAL_PATH <path> <out-var> [BASE_DIRECTORY <dir>] [EXPAND_TILDE]) # 转为绝对路径
#   file(RELATIVE_PATH <out-var> <directory> <file>) # 计算相对路径
#   file({TO_CMAKE_PATH | TO_NATIVE_PATH} <path> <out-var>) # 转换路径为 CMake 格式或操作系统格式

# Transfer 传输
#   file(DOWNLOAD <url> [<file>] [...]) # 下载
#   file(UPLOAD <file> <url> [...]) # 上传

# Locking 加锁
#   file(LOCK <path> [...])

# Archiving 归档，支持 7zip gnutar pax paxr raw zip 格式
#   file(ARCHIVE_CREATE OUTPUT <archive> PATHS <paths>... [...])
#   file(ARCHIVE_EXTRACT INPUT <archive> [...])

message("    --  列表操作喵 \n")

# Reading 读
#   list(LENGTH <list> <out-var>) # 获取列表元素数量
#   list(GET <list> <element index> [<index> ...] <out-var>) # 获取第 index 个元素
#   list(JOIN <list> <glue> <out-var>) # 连接为字符串， glue 为分隔符
#   list(SUBLIST <list> <begin> <length> <out-var>) # 截取

# Search 查
#   list(FIND <list> <value> <out-var>) # 查找，返回索引

# Modification 写
#   list(APPEND <list> [<element>...]) # 追加元素，尾插
#   list(FILTER <list> {INCLUDE | EXCLUDE} REGEX <regex>) # 过滤
#   list(INSERT <list> <index> [<element>...]) # 插入元素
#   list(POP_BACK <list> [<out-var>...]) # 弹出最后一个
#   list(POP_FRONT <list> [<out-var>...]) # 弹出第一个
#   list(PREPEND <list> [<element>...]) # 头插
#   list(REMOVE_ITEM <list> <value>...) # 移除值为 value 的元素
#   list(REMOVE_AT <list> <index>...) # 移除 index 位置的元素
#   list(REMOVE_DUPLICATES <list>) # 去重
#   list(TRANSFORM <list> <ACTION> [...]) # 操作列表， ACTION 可为： APPEND, PREPEND, TOUPPER, TOLOWER, STRIP, GENEX_STRIP, REPLACE； SELECTOR 可为 AT FOR REGEX

# Ordering 排序
#   list(REVERSE <list>) # 反转
#   list(SORT <list> [COMPARE <compare>] [CASE <case>] [ORDER <order>]) # 排序， COMPARE 可为 STRING, FILE_BASENAME, NATURAL ； CASE 可为 SENSITIVE, INSENSITIVE； ORDER 可为 ASCENDING, DESCENDING

message("    --  字符串操作喵 \n")

# Search and Replace 查找替换
#   string(FIND <string> <substr> <out-var> [...]) # 在 string 查找 substr 的位置
#   string(REPLACE <match-string> <replace-string> <out-var> <input>...) # 替换
#   string(REGEX MATCH <match-regex> <out-var> <input>...) # 查找匹配正则表达式的位置
#   string(REGEX MATCHALL <match-regex> <out-var> <input>...) # 检查整个字符串是否符合正则表达式
#   string(REGEX REPLACE <match-regex> <replace-expr> <out-var> <input>...) # 正则替换

# Manipulation 字符串操作
#   string(APPEND <string-var> [<input>...]) # 尾插
#   string(PREPEND <string-var> [<input>...]) # 头插
#   string(CONCAT <out-var> [<input>...]) # 连接
#   string(JOIN <glue> <out-var> [<input>...]) # 连接
#   string(TOLOWER <string> <out-var>) # 转小写
#   string(TOUPPER <string> <out-var>) # 转大写
#   string(LENGTH <string> <out-var>) # 获取长度
#   string(SUBSTRING <string> <begin> <length> <out-var>) # 截取
#   string(STRIP <string> <out-var>) # 删除前导和尾随空格
#   string(_STRIP <string> <out-var>) # 删除 GENEX 生成表达式
#   string(REPEAT <string> <count> <out-var>) # 重复 count 次

# Comparison 比较
#   string(COMPARE <op> <string1> <string2> <out-var>) # 比较， op 可为 LESS GREATER EQUAL NOTEQUAL LESS_EQUAL GREATER_EQUAL

# Hashing 哈希
#   string(<HASH> <out-var> <input>) # 计算哈希值

# Generation 生成
#   string(ASCII <number>... <out-var>) # 数字转字符串
#   string(HEX <string> <out-var>) # 转十六进制
#   string(CONFIGURE <string> <out-var> [...]) # 类似  configure_file 命令
#   string(MAKE_C_IDENTIFIER <string> <out-var>) # 非字母数字字符转换为下划线
#   string(RANDOM [<option>...] <out-var>) # 生成随机字符串
#   string(TIMESTAMP <out-var> [<format string>] [UTC]) # 时间字符串
#   string(UUID <out-var> ...) # 获取 UUID

# JSON
#   string(JSON <out-var> [ERROR_VARIABLE <error-var>]
#     {GET | TYPE | LENGTH} <json-string> <member|index> [<member|index> ...]) # 获取元素的值、类型、长度
#   string(JSON <out-var> [ERROR_VARIABLE <error-var>]
#     REMOVE <json-string> <member|index> [<member|index> ...]) # 删除一个元素
#   string(JSON <out-var> [ERROR_VARIABLE <error-var>]
#     MEMBER <json-string> [<member|index> ...] <index>) # 获取第 <index> 个成员的名称，需要对象类型的元素
#   string(JSON <out-var> [ERROR_VARIABLE <error-var>]
#     SET <json-string> <member|index> [<member|index> ...] <value>) # 设置值
#   string(JSON <out-var> [ERROR_VARIABLE <error-var>]
#     EQUAL <json-string1> <json-string2>) # 比较两个 JSON 对象是否相等

message("    --  属性喵 \n")

# 使用 define_property 定义一个属性喵
# define_property(<GLOBAL | DIRECTORY | TARGET | SOURCE | TEST | VARIABLE | CACHED_VARIABLE> # 设置属性的范围
#   PROPERTY <name> # 属性的名称
#   [INHERITED] # 继承自高级作用域的属性。指定之后，获取属性在本级作用域未查到时，会从更高的作用域查找
#   [BRIEF_DOCS <brief-doc> [docs...]] # 属性的简介文档
#   [FULL_DOCS <full-doc> [docs...]] # 属性的完整文档
#   [INITIALIZE_FROM_VARIABLE <variable>]) # 从变量初始化，只用于 TARGET 的属性

# 使用 set_property 设置属性的值喵
# set_property(<
#     GLOBAL |
#     DIRECTORY [<dir>] |
#     TARGET [<target1> ...] |
#     SOURCE [<src1> ...]
#       [DIRECTORY <dirs> ...]
#       [TARGET_DIRECTORY <targets> ...] |
#     INSTALL [<file1> ...] |
#     TEST [<test1> ...]
#       [DIRECTORY <dir>] |
#     CACHE [<entry1> ...]
#   > # 前面都是属性的作用域喵
#   [APPEND] [APPEND_STRING] # APPEND 按列表追加， APPEND_STRING 按字符串追加
#   ROPERTY <name> [<value1> ...]) # 属性名称和值喵

# 使用 get_property 获取属性的值喵，查找属性没找到均为 NOTFOUND
# get_property(<variable> # 保存结果的变量
#   <
#     GLOBAL |
#     DIRECTORY [<dir>] |
#     TARGET <target> |
#     SOURCE <source>
#       [DIRECTORY <dir> | TARGET_DIRECTORY <target>] |
#     INSTALL <file> |
#     TEST <test>
#       [DIRECTORY <dir>] |
#     CACHE <entry> |
#     VARIABLE
#   > # 前面都是属性的作用域喵
#   PROPERTY <name> # 属性名喵
#   [SET | DEFINED | BRIEF_DOCS | FULL_DOCS]) # 依次为 是否置值 是否定义 简要文档 完整文档

# 其他属性操作函数喵
#   全局属性喵，只读喵
#     get_cmake_property(<variable> <property>) # 查找属性
#   文件夹属性喵
#     set_directory_properties(PROPERTIES <prop1> <value1> [<prop2> <value2>] ...) # 设置属性
#     get_directory_property(<variable> [DIRECTORY <dir>] <prop-name>) # 查找属性
#     get_directory_property(<variable> [DIRECTORY <dir>] DEFINITION <var-name>) # 从目录 dir 查找变量 var-name
#   目标属性
#     set_target_properties(<targets> ... PROPERTIES <prop1> <value1> [<prop2> <value2>] ...) # 设置属性
#     get_target_property(<variable> target property)  # 查找属性
#   源文件属性
#     set_source_files_properties(<files> ...  [DIRECTORY <dirs> ...] [TARGET_DIRECTORY <targets> ...] PROPERTIES <prop1> <value1> [<prop2> <value2>] ...) # 设置属性
#     get_source_file_property(<variable> <file> [DIRECTORY <dir> | TARGET_DIRECTORY <target>] <property>) # 查找属性

add_subdirectory(Proj_TestForDirProp) # 需用 add_subdirectory 加载文件夹喵
get_directory_property(dir_res_prop DIRECTORY Proj_TestForDirProp FOR_TEST_PROP)
message("文件夹属性 FOR_TEST_PROP 是 : " ${dir_res_prop})
get_directory_property(dir_res_def DIRECTORY Proj_TestForDirProp DEFINITION Var_For_Test_Prop)
message("文件夹变量 Var_For_Test_Prop 是 : " ${dir_res_def})
get_property(dir_res_prop_doc DIRECTORY Proj_TestForDirProp PROPERTY FOR_TEST_PROP BRIEF_DOCS)
message("文件夹属性 FOR_TEST_PROP 的文档是 : " ${dir_res_prop_doc} "\n")

message("    --  其他命令喵 \n")

message("其他命令： ")
# 获取系统信息喵
# cmake_host_system_information(RESULT <variable> QUERY <key> ...) # 查询系统信息
# cmake_host_system_information(RESULT <variable> QUERY WINDOWS_REGISTRY <key> ...) # 查询 Windows 注册表
cmake_host_system_information(RESULT sys_pretty_name QUERY DISTRIB_PRETTY_NAME)
message("sys_pretty_name: ${sys_pretty_name}")
cmake_host_system_information(RESULT sys_distro QUERY DISTRIB_INFO)
foreach(VAR IN LISTS sys_distro)
  message("${VAR} = `${${VAR}}`")
endforeach()

# 获取本机名喵
site_name(var_site_name)
message("the site name : " ${var_site_name})

# 获取日志级别喵
cmake_language(GET_MESSAGE_LOG_LEVEL log_level)
message("日志级别： " ${log_level} "\n")
